// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Mr_Rakun

//@version=5
strategy("Advanced Position Management [Mr_Rakun]", overlay=true, currency=currency.USD, initial_capital=10000)

// Strategy
fastLength = input(10, "Fast MA Length", group = "Strategy")
slowLength = input(20, "Slow MA Length", group = "Strategy")

// Calculate MAs
fastMA = ta.ema(close, fastLength)
slowMA = ta.ema(close, slowLength)

// Plot MAs
plot(fastMA, color=color.blue, title="Fast MA")
plot(slowMA, color=color.red, title="Slow MA")

// Define trading conditions
longCondition = ta.crossover(fastMA, slowMA)
shortCondition = ta.crossunder(fastMA, slowMA)

// Multiple take profit and multi-function stop loss
// --------- | ----------------------------
// Add below your own strategy from here. |
// --------- | ----------------------------

// Position Management Inputs
posManagement = input.bool(true, "========== Advanced Position Management ==========")
posType = input.string("Both", "Strategy Type", options=["Both", "Long", "Short"], group = "Strategy Type")
tp1Percent = input.float(2.0, "Take Profit 1 %                                               ", minval=0.1, maxval=20, step=0.1, group = "position management", inline = "tp1")
tp1PositionPercent = input.float(30.0, "Qty %", minval=1, maxval=100, step=0.1, group = "position management", inline = "tp1")

tp2Percent = input.float(4.0, "Take Profit 2 %                                               ", minval=0.1, maxval=20, step=0.1, group = "position management", inline = "tp2")
tp2PositionPercent = input.float(30.0, "Qty %", minval=1, maxval=100, step=0.1, group = "position management", inline = "tp2")
useTP2 = input.bool(true, "", group = "position management", inline = "tp2")

tp3Percent = input.float(6.0, "Take Profit 3 %                                               ", minval=0.1, maxval=20, step=0.1, group = "position management", inline = "tp3")
tp3PositionPercent = input.float(40.0, "Qty %", minval=1, maxval=100, step=0.1, group = "position management", inline = "tp3")
useTP3 = input.bool(true, "", group = "position management", inline = "tp3")

initialStopLossPercent = input.float(2.0, "Initial Stop Loss %", minval=0.1, maxval=10, step=0.1, group = "Stop Loss")

// Trailing Stop Inputs
trailingStopType = input.string("Percent", "Trailing Stop Type                                               ", options=["Percent", "Previous TP"], group = "Stop Loss", inline = "stopuse")
useTrailingStop = input.bool(true, "", group = "Stop Loss", inline = "stopuse")
trailingStopPercent = input.float(3, "Trailing Stop % (if Percent type)", minval=0.1, maxval=10, step=0.1, group = "Stop Loss")
trailingStopActivationPercent = input.float(3.0, "Trailing Stop Activation %", minval=0.1, maxval=10, step=0.1, group = "Stop Loss")

// Position Size Input
positionSizeUSD = input.float(1000, "Position Size (USD)", minval=10, step=10, group = "Order Size")


// Position management variables
var float entryPrice = na
var float currentStopLoss = na
var float tp1Price = na
var float tp2Price = na
var float tp3Price = na
var bool trailingStopActive = false
var float highestSinceEntry = na
var float lowestSinceEntry = na
var float initialPositionSizeUSD = na
var float tp1SizeUSD = na
var float tp2SizeUSD = na
var float tp3SizeUSD = na
var int lastTPHit = 0

// Function to calculate position size in asset units
calcPositionSize(usdAmount) =>
    math.round(usdAmount / close, 2)

// Function to calculate USD value for each TP level
calcTPSizeUSD(percent) =>
    math.round(initialPositionSizeUSD * (percent / 100), 2)

// Function to update trailing stop based on TP levels
updateTrailingStopTP(currentPrice, isLong, currentStop, entry, tp1, tp2, tp3, lastHit) =>
    newStop = currentStop
    newLastHit = lastHit
    if isLong
        if currentPrice >= tp3 and lastHit < 3
            newStop := tp2
            newLastHit := 3
        else if currentPrice >= tp2 and lastHit < 2
            newStop := tp1
            newLastHit := 2
        else if currentPrice >= tp1 and lastHit < 1
            newStop := entry
            newLastHit := 1
    else
        if currentPrice <= tp3 and lastHit < 3
            newStop := tp2
            newLastHit := 3
        else if currentPrice <= tp2 and lastHit < 2
            newStop := tp1
            newLastHit := 2
        else if currentPrice <= tp1 and lastHit < 1
            newStop := entry
            newLastHit := 1
    [newStop, newLastHit]

// Open positions
if (longCondition) and (posType == "Both" or posType == "Long") and (strategy.position_size == 0 or strategy.position_size < 0)
    entryPrice := close
    currentStopLoss := close * (1 - initialStopLossPercent / 100)
    tp1Price := close * (1 + tp1Percent / 100)
    tp2Price := close * (1 + tp2Percent / 100)
    tp3Price := close * (1 + tp3Percent / 100)
    trailingStopActive := false
    highestSinceEntry := close
    lastTPHit := 0
    initialPositionSizeUSD := positionSizeUSD
    strategy.entry("Long", strategy.long, qty=calcPositionSize(positionSizeUSD))
    tp1SizeUSD := calcTPSizeUSD(tp1PositionPercent)
    tp2SizeUSD := calcTPSizeUSD(tp2PositionPercent)
    tp3SizeUSD := calcTPSizeUSD(tp3PositionPercent)

if (shortCondition) and (posType == "Both" or posType == "Short") and (strategy.position_size == 0 or strategy.position_size > 0)
    entryPrice := close
    currentStopLoss := close * (1 + initialStopLossPercent / 100)
    tp1Price := close * (1 - tp1Percent / 100)
    tp2Price := close * (1 - tp2Percent / 100)
    tp3Price := close * (1 - tp3Percent / 100)
    trailingStopActive := false
    lowestSinceEntry := close
    lastTPHit := 0
    initialPositionSizeUSD := positionSizeUSD
    strategy.entry("Short", strategy.short, qty=calcPositionSize(positionSizeUSD))
    tp1SizeUSD := calcTPSizeUSD(tp1PositionPercent)
    tp2SizeUSD := calcTPSizeUSD(tp2PositionPercent)
    tp3SizeUSD := calcTPSizeUSD(tp3PositionPercent)

// Update trailing stop
if (strategy.position_size != 0 and useTrailingStop)
    isLong = strategy.position_size > 0
    currentPrice = isLong ? high : low
    profitPercent = isLong ? (currentPrice - entryPrice) / entryPrice * 100 : (entryPrice - currentPrice) / entryPrice * 100
    
    if (profitPercent >= trailingStopActivationPercent and not trailingStopActive)
        trailingStopActive := true
    
    if (trailingStopActive)
        if (trailingStopType == "Percent")
            newStopLoss = isLong ? currentPrice * (1 - trailingStopPercent / 100) : currentPrice * (1 + trailingStopPercent / 100)
            currentStopLoss := isLong ? math.max(currentStopLoss, newStopLoss) : math.min(currentStopLoss, newStopLoss)
        else if (trailingStopType == "Previous TP")
            [newStop, newLastHit] = updateTrailingStopTP(currentPrice, isLong, currentStopLoss, entryPrice, tp1Price, tp2Price, tp3Price, lastTPHit)
            currentStopLoss := newStop
            lastTPHit := newLastHit

// Close positions with USD-based quantities
if (strategy.position_size > 0)
    strategy.exit("TP1 Long", "Long", qty=calcPositionSize(tp1SizeUSD), limit=tp1Price)
    if (useTP2)
        strategy.exit("TP2 Long", "Long", qty=calcPositionSize(tp2SizeUSD), limit=tp2Price)
    if (useTP3)
        strategy.exit("TP3 Long", "Long", qty=calcPositionSize(tp3SizeUSD), limit=tp3Price)

if (strategy.position_size > 0 and ta.cross(low, currentStopLoss))  
    strategy.close("Long", "SL Long")

if (strategy.position_size < 0)
    strategy.exit("TP1 Short", "Short", qty=calcPositionSize(tp1SizeUSD), limit=tp1Price)
    if (useTP2)
        strategy.exit("TP2 Short", "Short", qty=calcPositionSize(tp2SizeUSD), limit=tp2Price)
    if (useTP3)
        strategy.exit("TP3 Short", "Short", qty=calcPositionSize(tp3SizeUSD), limit=tp3Price)

if (strategy.position_size < 0 and ta.cross(high, currentStopLoss))  
    strategy.close("Short", "SL Short")

// Plot stop loss and take profit levels
plot(strategy.position_size != 0 ? currentStopLoss : na, color=color.red, style=plot.style_linebr, title="Stop Loss")
plot(strategy.position_size != 0 ? tp1Price : na, color=color.green, style=plot.style_linebr, title="Take Profit 1")
plot(useTP2 and strategy.position_size != 0 ? tp2Price : na, color=color.lime, style=plot.style_linebr, title="Take Profit 2")
plot(useTP3 and strategy.position_size != 0 ? tp3Price : na, color=color.teal, style=plot.style_linebr, title="Take Profit 3")